﻿namespace CompanyPayRollSystem.BusinessLayer
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using CompanyPayRollSystem.Database;

    /// <summary>
    /// Manager for EmployeeSalaryItems table
    /// </summary>
    public class EmployeeSalaryItemsManager : EntityManager
    {

        /// <summary>
        /// Calculates the employee salary.
        /// </summary>
        /// <param name="employeeID">The employee ID.</param>
        /// <param name="month">The month.</param>
        /// <param name="year">The year.</param>
        /// <returns>Gross Salary</returns>
        public static double CalculateEmployeeSalary(int employeeID, int month, int year)
        {
            // TODO: calculate the employee basic salary + Incentives Percentage + bonus Percentage for the given month and year
            EmployeeSalaryItem employeeSalaryItem = GetEmployeeSalaryItems(employeeID, month, year);
            return CalculateEmployeeSalary(employeeSalaryItem);
        }

        /// <summary>
        /// Calculates the employee salary.
        /// </summary>
        /// <param name="employeeSalaryItem">The employee salary item.</param>
        /// <returns>Gross Salary</returns>
        public static double CalculateEmployeeSalary(EmployeeSalaryItem employeeSalaryItem)
        {
            // TODO: calculate the employee basic salary + Incentives Percentage + bonus Percentage for the given month and year
            double total;
            if (employeeSalaryItem != null)
            {
                total = employeeSalaryItem.Employee.Salary + ((employeeSalaryItem.Bonus + employeeSalaryItem.Incentive) * employeeSalaryItem.Employee.Salary);
            }
            else
            {
                total = employeeSalaryItem.Employee.Salary;
            }

            return total;
        }

        /// <summary>
        /// Marks as delivered.
        /// </summary>
        /// <param name="employeeSalaryItem">The employee salary item.</param>
        /// <param name="dateTime">The date time.</param>
        public static void MarkAsDelivered(EmployeeSalaryItem employeeSalaryItem, DateTime dateTime)
        {
            employeeSalaryItem.IsDelivered = true;
            employeeSalaryItem.DeliveryDate = dateTime;
            try
            {
                Context.SubmitChanges();
            }
            catch (Exception ex)
            {
                // Log Exception
                Utilities.Logger.LogException(ex);
                throw ex;
            }
        }

        /// <summary>
        /// Gets the employee salary items.
        /// </summary>
        /// <param name="employeeID">The employee ID.</param>
        /// <param name="month">The month.</param>
        /// <param name="year">The year.</param>
        /// <returns>returns the salary item of the specified employee in the specified month and year.</returns>
        public static EmployeeSalaryItem GetEmployeeSalaryItems(int employeeID, int month, int year)
        {
            EmployeeSalaryItem[] employeeSalaryItems = Context.EmployeeSalaryItems.Where(salaryItem => salaryItem.EmployeeID == employeeID && salaryItem.Month == month && salaryItem.Year == year).ToArray();
            if (employeeSalaryItems.Length != 1)
            {
                return null;
            }
            else
            {
                return employeeSalaryItems[0];
            }
        }

        /// <summary>
        /// Updates the employee salary items without saving.
        /// </summary>
        /// <param name="employeeID">The employee ID.</param>
        /// <param name="month">The month.</param>
        /// <param name="year">The year.</param>
        /// <param name="incentivePercentage">The incentive percentage.</param>
        /// <param name="bonusPercentage">The bonus percentage.</param>
        public static void SaveEmployeeSalaryItems(int employeeID, int month, int year, double incentivePercentage, double bonusPercentage)
        {
            // TODO: Set the employee Incentives and bonus for the given month and year.
            bool addedSuccessfully = true;
            try
            {
                addedSuccessfully = UpdateEmployeeSalaryItems(employeeID, month, year, incentivePercentage, bonusPercentage);
                Context.SubmitChanges();
            }
            catch (Exception ex)
            {
                // Log Exception
                Utilities.Logger.LogException(ex);
                throw ex;
            }
        }

        /// <summary>
        /// Saves the job level salary items.
        /// </summary>
        /// <param name="jobLevelID">The job level.</param>
        /// <param name="month">The month.</param>
        /// <param name="year">The year.</param>
        /// <param name="incentivePercentage">The incentive percentage.</param>
        /// <param name="bonusPercentage">The bonus percentage.</param>        
        public static void SaveJobLevelSalaryItems(int jobLevelID, int month, int year, double incentivePercentage, double bonusPercentage)
        {
            // TODO: Set the employee Incentives and bonus for the given month and year for all employees in given JobLevel
            List<Employee> employees = EmployeeManager.GetEmployees(null, jobLevelID);
            foreach (Employee employee in employees)
            {
                UpdateEmployeeSalaryItems(employee.EmployeeID, month, year, incentivePercentage, bonusPercentage);
            }

            try
            {
                Context.SubmitChanges();
            }
            catch (Exception ex)
            {
                // Log Exception
                Utilities.Logger.LogException(ex);
                throw ex;
            }
        }

        /// <summary>
        /// Saves the department salary items.
        /// </summary>
        /// <param name="departmentID">The department ID.</param>
        /// <param name="month">The month.</param>
        /// <param name="year">The year.</param>
        /// <param name="incentivePercentage">The incentive percentage.</param>
        /// <param name="bonusPercentage">The bonus percentage.</param>
        public static void SaveDepartmentSalaryItems(int departmentID, int month, int year, double incentivePercentage, double bonusPercentage)
        {
            // TODO: Set the employee Incentives and bonus for the given month and year for all employees in given department
            List<Employee> employees = EmployeeManager.GetEmployees(departmentID, null);
            foreach (Employee employee in employees)
            {
                UpdateEmployeeSalaryItems(employee.EmployeeID, month, year, incentivePercentage, bonusPercentage);
            }

            try
            {
                Context.SubmitChanges();
            }
            catch (Exception ex)
            {
                // Log Exception
                Utilities.Logger.LogException(ex);
                throw ex;
            }
        }

        /// <summary>
        /// Saves all employees salary items.
        /// </summary>
        /// <param name="month">The month.</param>
        /// <param name="year">The year.</param>
        /// <param name="incentivePercentage">The incentive percentage.</param>
        /// <param name="bonusPercentage">The bonus percentage.</param>
        public static void SaveAllEmployeesSalaryItems(int month, int year, double incentivePercentage, double bonusPercentage)
        {
            // TODO: Set the employee Incentives and bonus for the given month and year for all employees 
            List<Employee> employees = EmployeeManager.GetEmployees();
            foreach (Employee employee in employees)
            {
                UpdateEmployeeSalaryItems(employee.EmployeeID, month, year, incentivePercentage, bonusPercentage);
            }

            try
            {
                Context.SubmitChanges();
            }
            catch (Exception ex)
            {
                // Log Exception
                Utilities.Logger.LogException(ex);
                throw ex;
            }
        }

        /// <summary>
        /// Updates the employee salary items.
        /// </summary>
        /// <param name="employeeID">The employee ID.</param>
        /// <param name="month">The month.</param>
        /// <param name="year">The year.</param>
        /// <param name="incentivePercentage">The incentive percentage.</param>
        /// <param name="bonusPercentage">The bonus percentage.</param>
        /// <returns>True if the Salary Item was not delivered already.</returns>
        private static bool UpdateEmployeeSalaryItems(int employeeID, int month, int year, double incentivePercentage, double bonusPercentage)
        {
            bool alreadyExisting = true;
            EmployeeSalaryItem employeeSalaryItem = GetEmployeeSalaryItems(employeeID, month, year);
            if (employeeSalaryItem == null)
            {
                employeeSalaryItem = new EmployeeSalaryItem();
                employeeSalaryItem.EmployeeID = employeeID;
                employeeSalaryItem.Month = month;
                employeeSalaryItem.Year = year;
                employeeSalaryItem.IsDelivered = false;
                alreadyExisting = false;
            }
            else if (employeeSalaryItem.IsDelivered)
            {
                // salary cashed out already-> cannot be modified
                return false;
            }

            employeeSalaryItem.Bonus = bonusPercentage;
            employeeSalaryItem.Incentive = incentivePercentage;

            if (!alreadyExisting)
            {
                Context.EmployeeSalaryItems.InsertOnSubmit(employeeSalaryItem);
            }

            return true;
        }
    }
}